<?php
/**
 * Created by PhpStorm.
 * User: xiangfeng
 * Date: 2022/4/9
 * Time: 9:35 AM
 */

namespace app\api\service;


use app\api\extend\tools\JwtAuth;
use app\api\extend\tools\SimpleModelConnectRedis;
use app\api\http\exceptions\ApiErr;
use app\api\http\exceptions\ApiExceptions;
use think\Service;

class UserTokenService extends Service
{
    /**
     * 获取登录token
     * @param int $user_id 用户ID
     * @param int $role_id 角色ID
     * @return array
     * @throws ApiExceptions
     */
    public static function token(int $user_id, int $role_id = 1): array
    {
        $map = UserService::get($user_id, 'id as user_id,uname,phone,nickname,avatar,openid,certification_status');
        $jwtAuth = JwtAuth::getInstance();
        $token = $jwtAuth->setUid($user_id)->setRid($role_id)->encode_jwt_token()->getToken();
        if (empty($token)) throw new ApiExceptions(ApiErr::API_UNKNOWN_ERROR);
        $data = array_merge($map, [
            'token' => $token,
            'role_id' => $role_id,
        ]);
        $data['expire_time'] = self::expire($user_id, $role_id, $token, $data);
        return $data;
    }

    /**
     * 设置缓存(Token)有效期
     * @param int $user_id 用户ID
     * @param int $role_id 角色ID
     * @param string $token
     * @param array $data
     * @return int
     */
    protected static function expire(int $user_id, int $role_id, string $token, array $data): int
    {
        $redis = SimpleModelConnectRedis::getInstance();
        /********** 更新用户缓存 **********/
        $key = USER_TOKEN_PREFIX . $user_id . '' . $role_id;
        if ($redis->exists($key)) {
            $redis->expire(USER_TOKEN_PREFIX . $redis->get($key), 0);//移除用户上一次token
        }
        $user_token_key = USER_TOKEN_PREFIX . md5($token);
        $expire_time = USER_TOKEN_EXPIRE_TIME + rand(15, 50);//设置用户token有效期2个小时
        $redis->hMSet($user_token_key, $data, $expire_time);
        $redis->set($key, md5($token), $expire_time + rand(1, 3));
        return (time() + $expire_time);
    }

    public static function checkToken($token = ''): array
    {
        if (!empty($token)) {
            $jwtAuth = JwtAuth::getInstance();
            $jwtAuth->setToken($token);
            if ($jwtAuth->validateToken() && $jwtAuth->verifyToken()) {
                $user_id = $jwtAuth->decode_jwt_token()->getClaim('uid');
                $role_id = $jwtAuth->decode_jwt_token()->getClaim('rid');
                $data = [
                    'user_id' => $user_id,
                    'role_id' => $role_id
                ];
            }
        }
        return !empty($data) ? $data : [];
    }
}